import React, {Component, Fragment} from "react";
import TodoItem from "./TodoItem";
// import Test from "./Test"
import "./inputStyle.css"

class TodoList extends Component {
    constructor(props) {
        super(props);
        //当组件的state或者props发生改变的时候，render函数就会重新执行

        this.state = {
            inputValue: '',
            list: []
        }
        this.handleInputChange = this.handleInputChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
        this.handleDeleteItem = this.handleDeleteItem.bind(this);
    }

    /**
     * 在组件即将被挂载到页面是的时刻执行,即将被挂载到页面但是还没有被挂载到页面上
     */
    UNSAFE_componentWillMount() {
        console.log('componentWillMount')
    }

    /**
     *
     */
    componentDidMount() {
        console.log('componentDidMount')
    }

    /**
     * shouldComponentUpdate:判断组件是否需要被更新，
     * 返回false表示我不需要更新这个组件，一般都是返回true
     *
     * 组件被更新之前，它会自动执行
     * 要求返回一个boolean类型的返回结果
     */
    shouldComponentUpdate() {
        console.log('shouldComponentUpdate');
        return true;
    }

    /**
     * 组件被更新之前，它会自动执行，但是它在shouldComponentUpdate之后被执行，如果
     * shouldComponentUpdate 返回true，它才执行，如果返回false，这个函数就不会被执行了
     */
    componentWillUpdate() {
        console.log('componentWillUpdate');
    }

    /**
     * 组件更新完成之后它会被执行
     * @param prevProps
     * @param prevState
     * @param snapshot
     */
    componentDidUpdate(prevProps, prevState, snapshot) {
        console.log('componentDidUpdate');
    }

    /**
     * 当父组件的render函数被运行时，它的子组件的render都将被重新运行一次
     * 这是因为它的props发生了改变，也可以理解为因为它是父组件的一个子组件
     * @returns {JSX.Element}
     */
    render() {
        console.log('TodoList render')
        return (
            <Fragment>
                <label htmlFor='insertArea'>输入内容</label>
                <input
                    className='classInput'
                    id='insertArea'
                    /**
                    * value 和 inputValue做了绑定，也就是state里面的inputValue只要发生了变化，这个input框里面的值就会跟着变化，
                    * 同时input框监听了onChange事件，一旦我们往这个input框里面输入内容的时候，onChange绑定的方法（拿到最新的value并更新state里面inputValue的值）就会执行，
                    * state 里面inputValue的值发生变化，页面就会跟着变化
                    */
                    type="text" value={this.state.inputValue}
                    onChange={this.handleInputChange}
                    ref={(input1) => {
                        this.input = input1
                    }}
                />
                <button
                    onClick={this.handleSubmit}
                >提交
                </button>
                <ul ref={(ul) => {
                    //this.ul被创建的时候，指向的就是ul这个真实的DOM节点了
                    this.ul = ul
                }}>
                    {
                        this.getTotoItems()
                    }
                </ul>
                {/*<Test content={this.state.inputValue}/>*/}
            </Fragment>
        );
    }

    handleInputChange(e) {
        // const value = e.target.value;
        let value = this.input.value;//this.input指向的是 input，而这个input恰好是input标签对应的实际的DOM元素
        this.setState(() => ({
            inputValue: value
        }))
    }

    handleSubmit() {
        this.setState((prevState) => ({
            list: [...prevState.list, prevState.inputValue],
            inputValue: ''
        }), () => {
            /**
             * react中操作dom就会出现这样的问题，这是因为setState是一个异步函数，当调用handleSubmit的时候。
             * setState并不会立即执行，要等一会才执行
             * 如果你希望setState执行成功后再去获取页面上的DOM，正确的做法应该是
             * setState提供了第二个参数，也是一个函数，setState是异步的，当它的第一个函数完全的被执行好了之后才回去执行第二个函数
             * 实际上第二个参数是一个回调函数，会被执行,保证执行的时候，页面中的DOM结果已经被更新完毕了
             */
            console.log(this.ul.querySelectorAll('div').length)
        });
    }

    /**
     * TodoList并没接受任何的props，也就是说，它是一个顶层组件，它没有父组件，也就没有接受到任何父组件传递过来的props参数，因此，没有props参数的时候，这个生命周期函数
     * 是不会被执行的
     * @param nextProps
     * @param nextContext
     */
    componentWillReceiveProps(nextProps, nextContext) {
        console.log('componentWillReceiveProps')
    }

    getTotoItems() {
        return this.state.list.map((item, index) => {
            return <TodoItem key={index} context={item} index={index} handleDeleteItem={this.handleDeleteItem}/>
        })
    }

    handleDeleteItem(index) {
        this.setState((prevState) => {
            const list = [...prevState.list];
            list.splice(index, 1);
            return {list}
        })

    }
}

export default TodoList;